/**
 * list group and free, data put list and free list
 */

#include "syslist.h"

/**
 *  slists_add
 */
static int slists_add(pslists_t psl, int bfree)
{
    plist_head_t node, head;
    pslists_group_t psg;

    if ( !psl )
        return -EPERM;
    psg = psl->group;
    if ( !psg )
        return -EPERM;

    node = &(psl->node);
    if (bfree) {
        head = &(psg->free);
    } else {
        head = &(psg->group);
    }

    list_del_init(node);
    list_add_tail(node, head);

    return 0;

}

/**
 *  slists_pop
 */
static pslists_t slists_pop(pslists_group_t psg, int bfree)
{
    pslists_t  psl;
    plist_head_t node, head;

    if ( !psg )
        return NULL;

    if (bfree) {
        head = &(psg->free);
    } else {
        head = &(psg->group);
    }

    if ( list_empty_careful(head) ) {
        return NULL;
    }

    psl = list_first_entry(head, slists_t, node);
    node = &(psl->node);
    list_del_init(node);

    return psl;

}

/**
 *  slists_count
 */
static int slists_count(pslists_group_t psg, int bfree)
{
    int count = 0;
    plist_head_t node, n, head;

    if ( !psg )
        return -1;

    if (bfree) {
        head = &(psg->free);
    } else {
        head = &(psg->group);
    }

    if ( list_empty_careful(head) ) {
        return 0;
    }

    list_for_each_safe(node, n, head)
    {
        count++;
    }

    return count;

}

////////////////////////////////////////////////////////////////////////////////
/**
 * slists_group_init
 */
void slists_group_init(pslists_group_t psg)
{
    if (psg == NULL)
    	return;

    INIT_LIST_HEAD(&(psg->group));
    INIT_LIST_HEAD(&(psg->free));
}

/**
 * slists_group_deinit
 */
void slists_group_deinit(pslists_group_t psg)
{
    if (psg == NULL)
    	return;
}

/**
 * slists_init
 */
void slists_init(pslists_t psl)
{
    if (psl == NULL)
    	return;

    INIT_LIST_HEAD(&(psl->node));
    psl->group = NULL;
}

/**
 *  slists_free
 */
int slists_free(pslists_t psl)
{
    return slists_add(psl, 1);
}

/**
 *  slists_put
 */
int slists_put(pslists_t  psl)
{
    return slists_add(psl, 0);
}

/**
 *  slists_alloc
 */
pslists_t slists_alloc(pslists_group_t psg)
{
    return slists_pop(psg, 1);
}

/**
 *  slists_get
 */
pslists_t slists_get(pslists_group_t psg)
{
    return slists_pop(psg, 0);
}

/**
 *  slists_topnum
 */
int slists_topnum(pslists_group_t psg)
{
    return slists_count(psg, 0);
}
